package cn.woniu.wxy.handler;



import cn.woniu.wxy.service.SecurityServicce;
import cn.woniu.wxy.util.JWTUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * SpringSecurity 整合jwt过滤器
 * 功能1、判断除登陆请求外，是否携带了jwt，如果没有携带：直接放行，让后续的过滤器处理
 * 功能2、判断携带的jwt是否合法 。不合法：放掉不处理
 * 功能3、拿redis中的jwt和请求头的jwt做对比
 *          1、redis的jwt已经过期
 *          2、没失效，再把jwt的值对比一下
 *
 */
@Component
public class JWTFilter extends OncePerRequestFilter {

    @Autowired
    private SecurityServicce securityServicce;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    FilterChain filterChain) throws ServletException, IOException {
        //在请求头拿到jwt
        String jwt = httpServletRequest.getHeader("jwt");
//        System.out.println(jwt);
        if (jwt == null){
            //放给security其他的过滤器，该方法不做处理
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }


        //请求头是否合法验证
        if (!JWTUtil.checkJWT(jwt)){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }

        //获取jwt的用户信息
        String username = JWTUtil.parseUsername(jwt);
//
//        String requestIP = httpServletRequest.getRemoteHost();
//
//        String redisIP =(String) redisTemplate.opsForHash().get("loginStatus", username);
//        System.out.println("redisIP"+redisIP);
//        System.out.println("requestIP"+requestIP);
//        if(requestIP.equals(redisIP)){
//            //非同一地址的登录, 不允许登录,放行
//            filterChain.doFilter(httpServletRequest,httpServletResponse);
//            return;
//        }

        //拿到redis的jwt
        String resisJWT = redisTemplate.opsForValue().get("jwt:" + username);
        //判断redis是否有该jwt
        if (resisJWT==null){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }else if (!jwt.equals(resisJWT)){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }

        //给redis的jwt续期
        redisTemplate.opsForValue().set("jwt:"+username,jwt,10, TimeUnit.MINUTES);

        //生成security容器的凭证
        UserDetails userDetails = securityServicce.loadUserByUsername(username);
        Authentication usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());

        //往security容器放入凭证
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

        //本方法功能执行完了，交给下一个过滤器
        filterChain.doFilter(httpServletRequest,httpServletResponse);

    }
}
